//============================================================================
// Name        : trabaioUm.cpp
// Author      : Dizus e Sasquatch
// Version     :
// Copyright   : Que porra eh essa??? CopyRIGHT is WRONG! :-)
// Description : Hello World in C++, DISAS-style
//============================================================================

#include <iostream>
#include <string>

#include "./../includes/error.h"

#include "./../includes/pilhaDSE.hpp"
#include "./../includes/pilhaDDE.hpp"
#include "./../includes/pilhaE.hpp"
#include "./../includes/heapsort.hpp"

#include "./../includes/ordena.h"
#include "./../includes/precedence.h"
#include "./../includes/torreMalditona.h"
#include "./../includes/palindromo.h"

const int
SUCCESS = 0;

void
imprimeMenu();

void
contaPilha();

void
torreDehanoi();

void
posFixoSolver();

void
checkIsPalindromo();

void
doOrdenate();

int main(int argc, char** argv) 
{
	int
	choice = 0;
	
	while (choice != 7)
	{
		imprimeMenu();
		std::cin >>choice;
		switch (choice)
		{
		case 0:
			contaPilha();
			break;
		case 3:
			torreDehanoi();
			break;
		case 4:
		case 5:
		case 6:
			posFixoSolver();
			break;
		case 2:
			checkIsPalindromo();
			break;
		case 1:
			std::cout << "AINDA EM DESENVOLVIMENTO" << std::endl;
			break;
		}
	}
	
	
	return SUCCESS;
}

void
imprimeMenu()
{
	std::cout << "******************************************************************" << std::endl;
	std::cout << "*                                                                *" << std::endl;
	std::cout << "*     Trabalho de Estutura de dados Um                           *" << std::endl;	
	std::cout << "*             Ricardo Ungerer Garcia Simões                      *" << std::endl;
	std::cout << "*                 Gabriel Gilini                                 *" << std::endl;
	std::cout << "*                                                                *" << std::endl;
	std::cout << "*                                                                *" << std::endl;
	std::cout << "******************************************************************" << std::endl;
	
	
	std::cout << "Escolha o exercício:"     << std::endl <<
				 "0 - Conta elementos"      << std::endl <<
				 "1 - Ordenação de Números" << std::endl << 
				 "2 - Palindromo"           << std::endl <<
				 "3 - Torre de Hanoi"       << std::endl <<
				 "4 - testa Aninhamento"    << std::endl <<
				 "5 - to pos-fixo"          << std::endl <<
				 "6 - solver"               << std::endl << 
				 "7 - sair"                 << std::endl << ">>>>> :";
}

/***************************
* 							*
* Torre de Hanoi Malditona	*
* 							*
***************************/
void
torreDehanoi()
{
	torreMalditona
	torre(10);
	
	std::vector<unsigned short int>
	pin;
	
	unsigned short int
	origin;
	
	unsigned short int
	destination;
	
	try
	{
		
		while(!torre.checkWin())
		{ 
			for( int a = 1 ; a < 4 ; a++ )
			{
				
				std::cout << "pino " << a << std::endl;
				
				pin = torre.getPinStats(a);
				
				for( int i = 0 ; i < pin.size() ; i++ )
					std::cout << pin[i] << std::endl;
				
			}
			
			std::cin >> origin;
			
			std::cin >> destination;
			
			torre.moveRing( origin , destination );
			
		}
		
	}
	catch(error* e)
	{
		std::cout << e->report();
	}
	
	std::cout << std::endl << "YOU ARE TEH WINNAR!";
}

/***************************************
* 										*
*  Calculadora de P�s-Fixo Malditona	*
* 										*
***************************************/
void
posFixoSolver()
{
	mathExpression*
	mathExp = new mathExpression( "[25+(10/2)]" );
	
	std::string
	postFixed;
	try
	{
		if( mathExp->isValidExpression() )
			std::cout << "� v�lida!" << std::endl;
		else
			std::cout << "N�o � v�lida :(" << std::endl;
		
		std::cout << "p�s-fixa: " << mathExp->getPosFix() << std::endl;
		
		std::cout << "solucionando..." << std::endl << std::endl
					<< "resultado: " << mathExp->solveExpression() << std::endl;
		
		delete mathExp;
	}
	catch( error* e )
	{
		std::cout << e->report();
	}
}

void
contaPilha()
{
	pilha<unsigned short int>*
	pilha1 = new pilha<unsigned short int>;
	
	pilha<unsigned short int>*
	pilha2 = new pilha<unsigned short int>;
	
	int
	contador = 0;
		
	for( unsigned short int i = 1 ; i < 11 ; i++ )
	{
		pilha1->push( i );
		
		pilha2->push( i );
	}
	
	while( !pilha1->isEmpty() )
	{
		pilha1->pop();
		contador++;
	}
	
	std::cout << contador << std::endl;
	
	std::cout << pilha2->getSize();
}

void
checkIsPalindromo()
{
	std::string
	palavra;
	
	std::cout << "Digita a palavra a ser testada:";
	std::cin >> palavra;
	
	palindrom
	palindromChecker;
	
	palindromChecker.setWord(palavra);
	
	if ( palindromChecker.isPalindrom() )
	{
		std::cout << "É palindromo";
	}
	else
	{
		std::cout << "Não é palindromo";
	}
	
}

void
doOrdenate()
{
	pilha<int>
	numbers;
	
	int number;
	
	while (number != 42 )
	{
		std::cout << "digite um número ou 42 para ordena-los...";
		std::cin >> number;
		
		if (number != 42)
		{
			numbers.push(number);
		}
	}
	
	heapsort<int>
	pilhadeOrdenacao;
	
	pilhadeOrdenacao.addStack( numbers );
	
	while (! pilhadeOrdenacao.isEmpty() )
	{
		std::cout << pilhadeOrdenacao.getSmaler();
	}
}
	/*********************
	 * 					  *
	 * PilhaDSE Malditona *
	 * 					  *
	 *********************/
	/*
	pilhaDSE<unsigned short int>*
	pilha = new pilhaDSE<unsigned short int>;
	
	try
	{
		for( unsigned short int i = 1 ; i < 11 ; i++ )
		{
			pilha->push(i);
			
			std::cout << pilha->getInfo();
		}
		
		for( unsigned short int i = 1 ; i < 10 ; i++ )
		{
			pilha->pop();
			
			std::cout << pilha->getInfo();
		}
		
		std::cout << std::endl << std::endl << pilha->getInfo();
		
		pilha->setInfo(50);
		
		std::cout << std::endl << pilha->getInfo();
		
		if( !pilha->isEmpty() )
		{
			std::cout << std::endl << "pilha n�o est� vazia! esvaziando..." << std::endl;

			pilha->clear();
		}
		if( pilha->isEmpty() )
		{
			std::cout << "pilha vazia." << std::endl;
		}
		
		delete pilha;
		
	}
	catch( error* e )
	{
		std::cout << e->report();
		return -1;
	}
	
	return SUCCESS;
	*/
	
	 /***********************
	 * 						*
	 * 	PilhaDDE Malditona	*
	 * 						*
	 ***********************/
	/*
	pilhaDDE<unsigned short int>*
		pilha = new pilhaDDE<unsigned short int>;
		
		unsigned short int tmp;
		
		try
		{
			for( unsigned short int i = 1 ; i < 11 ; i++ )
			{
				pilha->empilha(i);
				
				if( !pilha->buscaTopo(tmp) )
				{
					std::cout << std::endl << "deu milho";
					return -1;
				}
				
				std::cout << tmp << std::endl;
			}
			
			for( unsigned short int i = 1 ; i < 10 ; i++ )
			{
				if( !pilha->desempilha( tmp ) )
				{
					std::cout << std::endl << "deu milho";
					return -1;
				}
				
				std::cout << tmp << std::endl;
			}
			
			pilha->buscaTopo( tmp );
			
			std::cout << std::endl << std::endl << tmp;
			 
			if( !pilha->alteraTopo(50) )
			{
				std::cout << std::endl << "deu milho";
				return -1;
			}
			
			pilha->buscaTopo( tmp );
			
			std::cout << std::endl << tmp;
			
			if( !pilha->testaVazia() )
			{
				std::cout << std::endl << "pilha n�o est� vazia! esvaziando..." << std::endl;
				pilha->reinicia();
			}
			if( pilha->testaVazia() )
			{
				std::cout << "pilha vazia." << std::endl;
			}
			
			delete pilha;
			
		}
		catch( error* e )
		{
			std::cout << e->report();
			return -1;
		}
		
		return SUCCESS;
	*/
	
	 /*********************
	 * 					  *
	 * 	PilhaE Malditona  *
	 * 					  *
	 *********************/
	/*
	pilhaE<unsigned short int>*
	pilha = new pilhaE<unsigned short int>(10);
	
	unsigned short int
	tmp;
	
	unsigned short int
	i;
	
	for( i = 1 ; !pilha->testaCheia() ; i++ )
	{
		
		pilha->empilha( i );
	
		pilha->buscaTopo( tmp );
	
		std::cout << tmp << std::endl;
	}
	
	for( ; !pilha->testaVazia() ; i-- )
	{
		pilha->desempilha( tmp );
		
		std::cout << tmp << std::endl;
	}
	
	pilha->empilha(  50 );
	
	pilha->alteraTopo( 100 );
	
	pilha->buscaTopo( tmp );
	
	std::cout << tmp << std::endl;
	
	pilha->reinicia();
	
	if( pilha->testaVazia() )
		std::cout << "pilha vazia" << std::endl;
	else
		std::cout << "deu milho :(" << std::endl;
	
	delete pilha;
	
	std::cout << "cheguei ao fim!";
	*/
